home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / sharware / dynarray / fastmem.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-04-28  |  12.1 KB  |  485 lines

  1. {+------------------------------------------------------------
  2.  | Unit FastMem
  3.  |
  4.  | Version: 1.1  Last modified: 04/28/96
  5.  |   Changes 1.0 -> 1.1
  6.  |     Modified the code to compile and run under Delphi 2.0
  7.  | Author : P. Below
  8.  | Project: Common utilities
  9.  | Description:
  10.  |   This Unit contains a number of routines to do memory moves,
  11.  |   fills and swaps as fast as possible. The routines are all
  12.  |   implemented in assembler; the Win32-version will generate
  13.  |   different code from the Win16 version.
  14.  |
  15.  |   The BASM code for the Win32 version preserves all registers
  16.  |   and uses stack calling convention to get around problems
  17.  |   with register usage when optimization is enabled. It could
  18.  |   be sped up by using register calling convention and saving
  19.  |   only the required registers. I've left that for a later date
  20.  |   since it requires some research into Delphi internals first.
  21.  |   The Win32 version is still not fully tested! 
  22.  |
  23.  |   This version will compile as is in BP 7
  24.  +------------------------------------------------------------}
  25. Unit FastMem;
  26. Interface
  27. {$IFDEF VER70}
  28. Type
  29.   Cardinal = Word;
  30. {$ENDIF}
  31.  
  32.   Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte );
  33.   {$IFDEF WIN32} STDCALL; {$ENDIF}
  34.   Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
  35.   {$IFDEF WIN32} STDCALL; {$ENDIF}
  36.   Procedure MemDWordFill(pTarget: Pointer;
  37.                          numDWords: Cardinal; value: LongInt );
  38.   {$IFDEF WIN32} STDCALL; {$ENDIF}
  39.   Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal);
  40.   {$IFDEF WIN32} STDCALL; {$ENDIF}
  41.   Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal );
  42.   {$IFDEF WIN32} STDCALL; {$ENDIF}
  43.  
  44. Implementation
  45.  
  46. {************************************************************
  47.  * Procedure MemFill
  48.  *
  49.  * Parameters:
  50.  *  pTarget : pointer to memory to fill
  51.  *  numBytes: number of bytes to fill
  52.  *  value   : byte value to fill with
  53.  * Description:
  54.  *  Like System.FillChar, only faster, since it fills in the largest
  55.  *  possible unit (word or dword) as far as possible.
  56.  * Error Conditions:
  57.  *  May generate a GPF if the memory area addressed by pTarget cannot
  58.  *  take numBytes bytes!
  59.  *
  60.  *Created: 05/11/95 16:53:42 by P. Below
  61.  ************************************************************}
  62. Procedure MemFill(pTarget: Pointer; numBytes: Cardinal; value: Byte ); Assembler;
  63. {$IFNDEF WIN32}
  64.     Asm
  65.       mov cx, numBytes
  66.       jcxz @done
  67.       mov al, value
  68.       mov ah, al
  69.       les di, pTarget
  70.       push cx
  71.       cld
  72.       shr cx, 1       (* fill words first *)
  73.       jz @moveone
  74.       rep stosw
  75.     @moveone:         (* fill remaining byte *)
  76.       pop cx
  77.       and cx, 1
  78.       jz  @done
  79.       stosb
  80.     @done:
  81.     End;
  82. {$ELSE}
  83.    { we assume flat memory model here with 32bit near pointers
  84.      and ds=es!
  85.      This code is UNTESTED!
  86.    }
  87.    asm
  88.      pushad
  89.      mov ecx, numBytes
  90.      or ecx, ecx
  91.      jz @done
  92.      mov al, value
  93.      mov ah, al
  94.      mov bx,ax
  95.      shl eax, 16
  96.      mov ax, bx
  97.      mov edi, pTarget
  98.      cld
  99.      push ecx
  100.      shr ecx, 2   (* fill dwords first *)
  101.      jz @fillrest
  102.      rep stosd
  103.    @fillrest:     (* fill rest bytewise *)
  104.      pop ecx
  105.      and ecx, 3
  106.    @fill:
  107.      jz @done
  108.      mov [ edi ], al
  109.      inc edi
  110.      dec ecx
  111.      jmp @fill
  112.    @done:
  113.      popad
  114.    end;
  115. {$ENDIF}
  116.  
  117. {************************************************************
  118.  * Procedure MemWordFill
  119.  *
  120.  * Parameters:
  121.  *  pTarget : pointer to memory to fill
  122.  *  numWords: number of words to fill
  123.  *  value   : word value to fill with
  124.  * Description:
  125.  *  Fills the target memory area with numWords copies of value.
  126.  * Error Conditions:
  127.  *  May generate a GPF if the memory area addressed by pTarget cannot
  128.  *  take numWord words!
  129.  *
  130.  *Created: 05/11/95 16:53:42 by P. Below
  131.  ************************************************************}
  132. Procedure MemWordFill(pTarget: Pointer; numWords: Cardinal; value: Word );
  133.   Assembler;
  134. {$IFNDEF WIN32}
  135.     Asm
  136.       mov cx, numWords
  137.       jcxz @done
  138.       mov ax, value
  139.       les di, pTarget
  140.       cld
  141.       rep stosw
  142.     @done:
  143.     End;
  144. {$ELSE}
  145.    { we assume flat memory model here with 32bit near pointers
  146.      and ds=es!
  147.      This code is UNTESTED!
  148.    }
  149.    asm
  150.      pushad
  151.      mov ecx, numWords
  152.      or ecx, ecx
  153.      jz @done
  154.      mov ax, value
  155.      mov bx,ax
  156.      shl eax, 16
  157.      mov ax, bx
  158.      mov edi, pTarget
  159.      cld
  160.      push ecx
  161.      shr ecx, 1   (* fill dwords first *)
  162.      jz @fillrest
  163.      rep stosd
  164.    @fillrest:     (* fill rest *)
  165.      pop ecx
  166.      and ecx, 1
  167.      jz @done
  168.      mov [ edi ], ax
  169.    @done:
  170.      popad
  171.    end;
  172. {$ENDIF}
  173.  
  174. {************************************************************
  175.  * Procedure MemDWordFill
  176.  *
  177.  * Parameters:
  178.  *  pTarget  : pointer to memory to fill
  179.  *  numDWords: number of dwords to fill
  180.  *  value    : dword value to fill with
  181.  * Description:
  182.  *  Fills the target memory area with numDWords copies of value.
  183.  * Error Conditions:
  184.  *  May generate a GPF if the memory area addressed by pTarget cannot
  185.  *  take numDWord dwords!
  186.  *
  187.  *Created: 05/11/95 16:53:42 by P. Below
  188.  ************************************************************}
  189. Procedure MemDWordFill(pTarget: Pointer; numDWords: Cardinal; value: LongInt );
  190.   Assembler;
  191. {$IFNDEF WIN32}
  192.     Asm
  193.       mov cx, numDWords
  194.       jcxz @done
  195.       push ds
  196.       mov ax, word ptr value
  197.       mov dx, word ptr value+2
  198.       lds bx, pTarget
  199.     @loop:
  200.       mov [ bx ], ax
  201.       inc bx
  202.       inc bx
  203.       mov [ bx ], dx
  204.       inc bx
  205.       inc bx
  206.       dec cx
  207.       jnz @loop
  208.       pop ds
  209.     @done:
  210.     End;
  211. {$ELSE}
  212.    { we assume flat memory model here with 32bit near pointers
  213.      and ds=es!
  214.      This code is UNTESTED!
  215.    }
  216.    asm
  217.      pushad
  218.      mov ecx, numDWords
  219.      or ecx, ecx
  220.      jz @done
  221.      mov eax, value
  222.      mov edi, pTarget
  223.      cld
  224.      rep stosd
  225.    @done:
  226.      popad
  227.    end;
  228. {$ENDIF}
  229.  
  230. Function CheckOverlap: Boolean; Assembler;
  231.   Asm
  232. {$IFNDEF WIN32}
  233.     (* assumes: ds:si source pointer, es:di target pointer
  234.                 cx number of bytes to copy.
  235.        returns: al = 0 if no overlap,
  236.                 al = 1 if overlap, in which case the pointers
  237.                 are returned corrected! *)
  238.     mov ax, ds     (* compare the selectors *)
  239.     mov bx, es
  240.     cmp ax, bx
  241.     jne @no_overlap
  242.     mov ax, si     (* selectors equal, check offset parts *)
  243.     cmp ax, di     (* target <= source is never a problem *)
  244.     jnb @no_overlap
  245.     add ax, cx     (* check for source+count > target, which signifies *)
  246.     cmp ax, di     (* problematic overlap *)
  247.     jna @no_overlap
  248.     mov ax, 1      (* we have overlap, correct pointers to point at *)
  249.     add si, cx     (* last byte in source and target range *)
  250.     add di, cx
  251.     dec si
  252.     dec di
  253.     jmp @done
  254.   @no_overlap:
  255.     sub ax, ax
  256.   @done:
  257. {$ELSE}
  258.     (* assumes: esi source pointer, edi target pointer
  259.                 ecx number of bytes to copy.
  260.        returns: al = 0 if no overlap,
  261.                 al = 1 if overlap, in which case the pointers
  262.                 are returned corrected! *)
  263.     mov eax, esi     (* selectors equal by default, check offset parts *)
  264.     cmp eax, edi
  265.     jnb @no_overlap
  266.     add eax, ecx     (* for source+count > target, which signifies *)
  267.     cmp eax, edi     (* overlap *)
  268.     jna @no_overlap
  269.     mov eax, 1
  270.     add esi, ecx
  271.     add edi, ecx
  272.     dec esi
  273.     dec edi
  274.     jmp @done
  275.   @no_overlap:
  276.     sub eax, eax
  277.   @done:
  278. {$ENDIF}
  279.   End;
  280.  
  281. {************************************************************
  282.  * Procedure MemMove
  283.  *
  284.  * Parameters:
  285.  *  pSource  : pointer to source memory
  286.  *  pTarget  : pointer to target memory
  287.  *  numBytes : number of bytes to copy
  288.  * Description:
  289.  *  Like System.Move, only faster for larger numbers of bytes,
  290.  *  since it does the copy word or dword-wise, as far as possible.
  291.  *  The procedure checks for overlap of source and target regions
  292.  *  and performs the copy from highest address backwards, if the
  293.  *  regions overlap in a problematic way. The logic is optimized
  294.  *  for the source address beeing even (data word or dword-aligned).
  295.  *
  296.  * Error Conditions:
  297.  *  May cause a GPF if the memory addressed by the pointers has
  298.  *  a size of less than numBytes bytes.
  299.  *
  300.  *Created: 05/11/95 16:58:34 by P. Below
  301.  ************************************************************}
  302. Procedure MemMove(pSource, pTarget: Pointer; numBytes: Cardinal); Assembler;
  303. {$IFNDEF WIN32}
  304.   Asm
  305.     push ds
  306.     mov cx, numBytes
  307.     jcxz @done
  308.     lds si, pSource
  309.     les di, pTarget
  310.     call CheckOverlap
  311.     or al,al
  312.     jnz @overlap
  313.     cld             (* address ascending *)
  314.     push cx
  315.     shr cx, 1       (* move words first *)
  316.     jz @moveone
  317.     rep movsw
  318.   @moveone:         (* move remaining byte *)
  319.     pop cx
  320.     and cx, 1
  321.     jz  @done
  322.     movsb
  323.     jmp @done
  324.  
  325.   @overlap:
  326.     std
  327.     test cx, 1      (* check for odd count of bytes *)
  328.     je @moverest
  329.     movsb           (* if odd, move one byte first *)
  330.   @moverest:
  331.     shr cx, 1       (* count is now in words *)
  332.     jz @done
  333.     dec si
  334.     dec di
  335.     rep movsw       (* move rest as words *)
  336.     cld
  337.  
  338.   @done:
  339.     pop ds
  340.   End;
  341. {$ELSE}
  342.    { we assume flat memory model here with 32bit near pointers
  343.      and ds=es!
  344.      This code is UNTESTED!
  345.    }
  346.   asm
  347.     pushad
  348.     mov ecx, numBytes
  349.     or ecx, ecx
  350.     jz @done
  351.     mov esi, pSource
  352.     mov edi, pTarget
  353.     call CheckOverlap
  354.     or al,al
  355.     jnz @overlap
  356.     cld
  357.     push ecx
  358.     shr ecx, 2   (* move dwords first *)
  359.     jz @moverest
  360.     rep movsd
  361.   @moverest:     (* move rest bytewise *)
  362.     pop ecx
  363.     and ecx, 3
  364.     jz @done
  365.     rep movsb
  366.     jmp @done
  367.  
  368.   @overlap:
  369.     std
  370.     test ecx, 1     (* check for odd count of bytes *)
  371.     jz @move2
  372.     movsb           (* if odd, move one byte first *)
  373.   @move2:
  374.     shr ecx, 1
  375.     dec esi
  376.     dec edi
  377.     jz @done
  378.     test ecx, 1     (* check for odd count of words *)
  379.     jz @move3
  380.     movsw           (* if yes, move one word *)
  381.   @move3:
  382.     shr ecx, 1
  383.     jz @done
  384.     sub esi,2
  385.     sub edi,2
  386.     rep movsd
  387.     cld
  388.  
  389.   @done:
  390.     popad
  391.   end;
  392. {$ENDIF}
  393.  
  394. {************************************************************
  395.  * Procedure MemSwap
  396.  *
  397.  * Parameters:
  398.  *  pSource  : pointer to source memory
  399.  *  pTarget  : pointer to target memory
  400.  *  numBytes : number of bytes to swap
  401.  * Description:
  402.  *  exchanges the contents of the memory addressed by the two
  403.  *  pointers. These areas should never overlap or the results
  404.  *  will invariably be somewhat strange! 
  405.  * Error Conditions:
  406.  *  May cause a GPF if the memory addressed by the pointers has
  407.  *  a size of less than numBytes bytes.
  408.  *
  409.  *Created: 05/11/95 16:58:34 by P. Below
  410.  ************************************************************}
  411. Procedure MemSwap(pSource, pTarget: Pointer; numBytes: Cardinal ); Assembler;
  412. {$IFNDEF WIN32}
  413.     Asm
  414.       push ds
  415.       mov cx, numBytes
  416.       jcxz @done
  417.       lds si, pSource
  418.       les di, pTarget
  419.       cmp cx, 1
  420.       je @swapone
  421.     @loop:
  422.       mov ax, [ si ]
  423.       xchg ax, es:[ di ]
  424.       mov [ si ], ax
  425.       inc si
  426.       inc si
  427.       inc di
  428.       inc di
  429.       dec cx
  430.       dec cx
  431.       jz @done
  432.       cmp cx, 1
  433.       ja @loop
  434.     @swapone:
  435.       mov al, [ si ]
  436.       xchg al, es:[ di ]
  437.       mov [ si ], al
  438.     @done:
  439.       pop ds
  440.     End;
  441. {$ELSE}
  442.    { we assume flat memory model here with 32bit near pointers
  443.      and ds=es!
  444.      This code is UNTESTED!
  445.    }
  446.    asm
  447.      pushad
  448.      mov ecx, numBytes
  449.      or ecx, ecx
  450.      jz @done
  451.      mov esi, pSource
  452.      mov edi, pTarget
  453.      cmp ecx, 3
  454.      jna @swapremains
  455.    @loop:
  456.      mov eax, [ esi ]
  457.      xchg eax, [ edi ]
  458.      mov [ esi ], eax
  459.      add esi, 4
  460.      add edi, 4
  461.      sub ecx, 4
  462.      jz @done
  463.      cmp ecx, 3
  464.      ja @loop
  465.    @swapremains:
  466.      cmp ecx, 1
  467.      je @swapone
  468.      mov ax, [ esi ]
  469.      xchg ax, [ edi ]
  470.      mov [ esi ], ax
  471.      add esi, 2
  472.      add edi, 2
  473.      sub ecx, 2
  474.      jz @done
  475.    @swapone:
  476.      mov al, [ esi ]
  477.      xchg al, [ edi ]
  478.      mov [ esi ], al
  479.    @done:
  480.      popad
  481.    end;
  482. {$ENDIF}
  483.  
  484. End.
  485.